package sys

/*******************************************************************************
Copyright:cloud
Author:cloudapex@126.com
Version:1.0
Date:2020-06-12
Description: 组织相关接口
*******************************************************************************/
import (
	"permissions/api/cache"
	"permissions/model"

	"gitee.com/cloudapex/ulern/htp"
	"gitee.com/cloudapex/ulern/util"
	"github.com/gin-gonic/gin"
)

/*
 * 描述: 组织列表
 * 路由: /group/list
 * 方法: GET
 *********************************************************************/
type GroupList struct {
	Name  string `form:"name" binding:"omitempty,max=64"` // 组名
	State int    `form:"state" binding:"omitempty"`       // 状态(1:正常;2:失效)
}

func (this *GroupList) Handle(c *gin.Context) htp.Response {
	//user := comm.CurrUser(c)

	items, err := (&model.Group{
		Name:  this.Name,
		State: this.State,
	}).Find()
	if err != nil {
		return htp.RespDBErr("", err)
	}
	return htp.RespOK("", &struct {
		List []model.Group `json:"list"`
	}{items})
}

/*
 * 描述: 组织树表
 * 路由: /group/tree
 * 方法: GET
 *********************************************************************/
type GroupTree struct{}

func (this *GroupTree) Handle(c *gin.Context) htp.Response {
	//user := comm.CurrUser(c)

	items, err := (&model.Group{}).FindTree()
	if err != nil {
		return htp.RespDBErr("", err)
	}
	return htp.RespOK("", &struct {
		List []model.GroupLable `json:"list"`
	}{items})
}

/*
 * 描述: 新增组织
 * 路由: /group/add
 * 方法: POST
 *********************************************************************/
type GroupAdd struct {
	ParentId int64  `form:"parentid" json:"parentid" binding:"omitempty"` // 父Id
	Icon     string `form:"icon" json:"icon" binding:"omitempty"`         // 图标
	Name     string `form:"name" json:"name" binding:"required,max=64"`   // 组名
	Order    int    `form:"order" json:"order" binding:"omitempty"`       // 排序值
	State    int    `form:"state" json:"state" binding:"required"`        // 状态(1:正常;2:失效)
}

func (this *GroupAdd) Handle(c *gin.Context) htp.Response {
	//user := comm.CurrUser(c)

	p := &model.Group{Id: this.ParentId}
	if this.ParentId != 0 {
		if has, err := p.Load(); !has || err != nil {
			return htp.RespDBErr("上级用户组不存在", err)
		}
	}

	m := model.Group{
		ParentId: this.ParentId,
		NodePath: model.NodePath(p.NodePath, p.Id),
		Icon:     this.Icon,
		Name:     this.Name,
		Tntyp:    model.ETreeNode_Leaf,
		Order:    this.Order,
		State:    this.State,
	}
	if _, err := m.Create(); err != nil {
		return htp.RespDBErr("创建用户组失败", err)
	}

	// 把父节点的角色关联下沉
	if p.Tntyp == model.ETreeNode_Leaf {
		if _, err := (&model.Group{Tntyp: model.ETreeNode_Base}).Update(p.Id); err != nil {
			return htp.RespDBErr("更新父级用户组类型失败", err)
		}
		if _, err := (&model.GroupRole{}).UpdGroup(p.Id, m.Id); err != nil {
			return htp.RespDBErr("更新父级用户组成员失败", err)
		}
	}
	return htp.RespOK("", &struct {
		Id int64 `json:"id"` // 用户组Id
	}{m.Id})
}

/*
 * 描述: 编辑组织
 * 路由: /group/upd
 * 方法: POST
 *********************************************************************/
type GroupUpd struct {
	Id    int64  `form:"id" json:"id" binding:"required"`            // 组Id
	Icon  string `form:"icon" json:"icon" binding:"omitempty"`       // 图标
	Name  string `form:"name" json:"name" binding:"required,max=64"` // 组名
	Order int    `form:"order" json:"order" binding:"omitempty"`     // 排序值
	State int    `form:"state" json:"state" binding:"required"`      // 状态(1:正常;2:失效)
}

func (this *GroupUpd) Handle(c *gin.Context) htp.Response {
	//user := comm.CurrUser(c)

	m := model.Group{
		Id:    this.Id,
		Icon:  this.Icon,
		Name:  this.Name,
		Order: this.Order,
		State: this.State,
	}
	// 更新记录, 允许后面的几个字段被重置为默认值
	if _, err := m.Update(this.Id, "icon", "order"); err != nil {
		return htp.RespDBErr("", err)
	}

	return htp.RespOK("", nil)
}

/*
 * 描述: 删除组织
 * 路由: /group/del
 * 方法: POST
 *********************************************************************/
type GroupDel struct {
	Id int64 `form:"id" json:"id" binding:"required"` // 用户组Id
}

func (this *GroupDel) Handle(c *gin.Context) htp.Response {
	//user := comm.CurrUser(c)

	// for self
	eff, err := (&model.Group{}).Delete(this.Id)
	if err != nil {
		return htp.RespDBErr("", err)
	}
	if eff == 0 {
		return htp.RespErr(htp.CodeTargetNotFound, "此用户组不存在", nil)
	}

	// for user cache
	util.Goroutine("HandUserRoles", func() { // 更新用户角色缓存
		// 影响的哪些用户
		uIds, err := (&model.UserGroup{GroupId: this.Id}).FindIds()
		if err != nil {
			util.Error("UserChoose.FindIds err:%v", err)
		}

		if err := cache.HandUserRoles(uIds, false); err != nil {
			util.Error("UserChoose.HandUserRoles err:%v", err)
		}
	})

	// for user group
	if _, err := (&model.UserGroup{}).Delete(0, this.Id); err != nil {
		return htp.RespDBErr("用户组织操作失败", err)
	}

	// for group role
	if _, err := (&model.GroupRole{}).Delete(this.Id, 0); err != nil {
		return htp.RespDBErr("用户组角色操作失败", err)
	}
	return htp.RespOK("", nil)
}

/*
 * 描述: 获取组织角色Ids
 * 路由: /group/choice
 * 方法: GET
 *********************************************************************/
type GroupChoice struct {
	Id int64 `form:"id" binding:"required"` // 用户组Id
}

func (this *GroupChoice) Handle(c *gin.Context) htp.Response {
	//user := comm.CurrUser(c)

	ids, err := (&model.GroupRole{GroupId: this.Id}).FindIds()
	if err != nil {
		return htp.RespDBErr("", err)
	}
	return htp.RespOK("", &struct {
		Ids []int64 `json:"ids"` // 角色Ids
	}{ids})
}

/*
 * 描述: 修改组织角色Ids
 * 路由: /group/choose
 * 方法: POST
 *********************************************************************/
const ( // 错误码
	EGChoose_MisType htp.ECode = iota + 1 // 只有叶子节点组可以绑定角色
)

type GroupChoose struct {
	GId  int64   `form:"gid" json:"gid" binding:"required"`    // 角色Id
	RIds []int64 `form:"rids" json:"rids" binding:"omitempty"` // 权限Ids
}

func (this *GroupChoose) Handle(c *gin.Context) htp.Response {
	//user := comm.CurrUser(c)

	mGroup := model.Group{Id: this.GId}
	if has, err := mGroup.Load(); !has || err != nil {
		return htp.RespDBErr("此用户组不存在", err)
	}

	if mGroup.Tntyp != model.ETreeNode_Leaf {
		return htp.RespErr(EGChoose_MisType, "只有叶子节点组可以绑定角色", nil)
	}

	if vry, err := (&model.Role{}).VerifyIds(this.RIds); !vry || err != nil {
		return htp.RespDBErr("角色验证失败", err)
	}

	mGR := model.GroupRole{}
	if _, err := mGR.Delete(this.GId, 0); err != nil {
		return htp.RespDBErr("用户组角色操作失败", err)
	}

	if err := mGR.Insert(this.GId, this.RIds); err != nil {
		return htp.RespDBErr("用户组角色更新失败", err)
	}

	util.Goroutine("HandUserRoles", func() { // 更新用户角色缓存
		// 影响的哪些用户
		uIds, err := (&model.UserGroup{GroupId: this.GId}).FindIds()
		if err != nil {
			util.Error("UserChoose.FindIds err:%v", err)
		}

		if err := cache.HandUserRoles(uIds, false); err != nil {
			util.Error("UserChoose.HandUserRoles err:%v", err)
		}
	})
	return htp.RespOK("", nil)
}
